package com.cek.tdrive;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.cek.tdrive.data.TDistance;
import com.cek.tdrive.data.TRoute;
import com.cek.tdrive.database.DbManager;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

/**
 * Servlet implementation class Route
 */
@WebServlet("/Route")
public class Route extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public Route() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		String startPlace = request.getParameter("startplace");
		String endPlace = request.getParameter("endplace");
		findRoute(request, response, startPlace, endPlace);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
	}

	private void findRoute(HttpServletRequest request,
			HttpServletResponse response, String startPlace, String endPlace)
			throws IOException {
		System.out.println("##Finding Route ");
		String encodeStartPlace = "";
		String encodeEndPlace = "";
		try {
			encodeStartPlace = URLEncoder.encode(startPlace, "UTF-8");
			encodeEndPlace = URLEncoder.encode(endPlace, "UTF-8");

		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		String url = "http://maps.googleapis.com/maps/api/directions/json?"
				+ "origin=" + encodeStartPlace + "&destination="
				+ encodeEndPlace
				+ "&sensor=false&mode=driving&alternatives=true";
		response.setContentType("application/json");
		// Get the printwriter object from response to write the required json
		// object to the output stream
		PrintWriter out = response.getWriter();
        //url = "http://maps.googleapis.com/maps/api/directions/json?origin=8.520695,%2076.941956&destination=8.528844,%2076.922215&sensor=false";
		try {
			System.out.println("In trying....");
			// String encodeUrl = URLEncoder.encode(url, "UTF-8");
			URL googleSearch = new URL(url);
			System.out.println("url = " + url);
			URLConnection gs = googleSearch.openConnection();
			BufferedReader in = new BufferedReader(new InputStreamReader(
					gs.getInputStream()));
			System.out.println("After connecting...");
			String inputLine;
			String jsonObject = "";

			while ((inputLine = in.readLine()) != null) {
				jsonObject += inputLine;
				// System.out.println(inputLine);

			}
			in.close();

			// out.print(jsonObject);
			// out.flush();

			JsonElement jelement = new JsonParser().parse(jsonObject);
			JsonObject jobject = jelement.getAsJsonObject();

			JsonArray routes = jobject.getAsJsonArray("routes");

			JsonArray steps[] = new JsonArray[routes.size()];
			
			// route.setSourceLat(sourceLat)
			ArrayList<TRoute> routesOptions = new ArrayList<TRoute>();
			DbManager db=DbManager.getInstance();
			System.out.println("routes : " + routes.size());
			String pointsWithoutQuotes[] = new String[routes.size()];
			for (int i = 0; i < routes.size(); i++) {

				JsonElement legs = routes.get(i).getAsJsonObject()
						.getAsJsonArray("legs");
				JsonArray legsArray = legs.getAsJsonArray();
				//overview_polyline
				
				 
				JsonElement overViewPolyLine = routes.get(i).getAsJsonObject().get("overview_polyline");
				String pointsWithQuotes = overViewPolyLine.getAsJsonObject().get("points").toString();
				int len = pointsWithQuotes.length();
				
			   pointsWithoutQuotes[i] = pointsWithQuotes.substring(1,len-1);
				
				//System.out.println("overViewPolyLine :: "+overViewPolyLine.getAsJsonObject().get("points").toString());
				JsonElement stepsElement = legsArray.get(0).getAsJsonObject()
						.getAsJsonArray("steps");
				steps[i] = stepsElement.getAsJsonArray();
				System.out.println("steps size :" + steps[i].size());
			}
			// for(int i=0;i<routes.size();i++)
			// for(int j=0;j<steps[i].size();j++) {
			for (int i=0;i<routes.size();i++) {
				TRoute route = new TRoute();
				ArrayList<TDistance> points = new ArrayList<TDistance>();
				long totalTDuration=0;
				long totalGDuration=0;
			for (int j = 0; j < steps[i].size(); j++) {
				TDistance tDistance = new TDistance();

				JsonObject step1 = steps[i].get(j).getAsJsonObject();
				JsonObject distance = (JsonObject) step1.get("distance");
				//System.out.println("distance=" + distance.get("value"));
				JsonObject duration = (JsonObject) step1.get("duration");
				
				///System.out.println("duration=" + duration.get("text"));
				// }
				JsonObject endLocation = (JsonObject) step1.get("end_location");
				JsonObject startLocation = (JsonObject) step1
						.get("start_location");
				
				JsonObject polyLineObj = (JsonObject) step1.get("polyline");
				String polyLine = polyLineObj.get("points").toString();
				int polyLineLength = polyLine.length();
				String polyLineWithoutQuotes = polyLine.substring(1, polyLineLength-1);
				polyLineWithoutQuotes = polyLineWithoutQuotes.replace("\\\\", "\\");
				/*System.out.println("end_location latitude="
						+ endLocation.get("lat"));
				System.out.println("end_location longitude="
						+ endLocation.get("lng"));
				System.out.println("startLocation latitude="
						+ startLocation.get("lat"));
				System.out.println("startLocation longitude="
						+ startLocation.get("lng"));*/

				double startLat = Double.parseDouble(startLocation.get("lat")
						.toString());
				double startLong = Double.parseDouble(startLocation.get("lng")
						.toString());

				double endLat = Double.parseDouble(endLocation.get("lat")
						.toString());
				double endLong = Double.parseDouble(endLocation.get("lng")
						.toString());
				
				long gMin = convertMinutesToLong(duration.get("text")
						.toString());
				
				long distanceLong = Long.parseLong(distance.get("value")
						.toString());
				 totalGDuration+=gMin;
				long tDriveDuration = db.getTdriveDuration(startLat, startLong, endLat, endLong, gMin);
				totalTDuration+=tDriveDuration;
				tDistance.setStartLat(startLat);
				tDistance.setStartLong(startLong);
				tDistance.setEndLat(endLat);
				tDistance.setEndLong(endLong);
				tDistance.setGoogleDuration(gMin);
				tDistance.setTdriveDuration(tDriveDuration);
				tDistance.setPolyLine(polyLineWithoutQuotes);
				tDistance.setDistance(distanceLong);
				points.add(tDistance);
			}
			
			System.out.println("### Total points to draw for route  : "+i + " = "+points.size());
			route.setSteps(points);
			route.setDesTdriveDuration(totalTDuration);
			route.setDesGDuration(totalGDuration);
			System.out.println("TDrive says " +totalTDuration);
			System.out.println("Google says " +totalGDuration);
			
		   String overViewPolyLine = pointsWithoutQuotes[i].replace("\\\\", "\\");
			route.setOverviewPolyLine(overViewPolyLine);
			routesOptions.add(route);
			}
			System.out.println("Total routes = "+routesOptions.size());
			Gson gson = new Gson();
			String json = gson.toJson(routesOptions);
			PrintWriter pw=response.getWriter();
			pw.println(json);

		} catch (Exception e) {
			System.out.println("Exception : " + e.getMessage());
		}
		
		
	}

	private long convertMinutesToLong(String minStr) {
		long min = 0;
		int minLoc = minStr.indexOf("min");
		String minPart = minStr.substring(1, minLoc - 1);
		min = Integer.parseInt(minPart) * 60 * 1000;
		return min;
	}

}
